package com.qijian.plug.capacity.approval;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.qijian.common.annotation.Log;
import com.qijian.common.core.domain.entity.FlowableBack;
import com.qijian.common.enums.ApprovalDescriptionEnum;
import com.qijian.common.enums.BusinessType;
import com.qijian.common.utils.StringUtils;
import com.qijian.common.utils.mybatis.WhereEntityTool;
import com.qijian.flowable.constant.FlowableConstant;
import com.qijian.flowable.domain.FlowableRecord;
import com.qijian.flowable.domain.query.FlowableRecordQuery;
import com.qijian.flowable.domain.vo.TaskVo;
import com.qijian.flowable.service.IFlowableRecordService;
import com.qijian.flowable.service.IFlowableTaskService;
import lombok.RequiredArgsConstructor;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author qijian
 */
@Component
@RequiredArgsConstructor
public class ApprovalBack extends ApprovalPlugWrapper<FlowableBack.Approval> {

    private final IFlowableRecordService flowableRecordService;
    private final IFlowableTaskService flowableTaskService;
    private final TaskService taskService;
    private final HistoryService historyService;


    private final RuntimeService runtimeService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doSomething(List<Object> args) {
        this.operation(args);
    }

    @Log(title = "流程退回", businessType = BusinessType.APPROVAL)
    protected void operation(List<Object> args) {
        if (CollectionUtil.isNotEmpty(args)) {
            FlowableRecord record = null;
            Long userId = null;
            String nickName = null;
            String msg = null;
            if (args.get(0) instanceof TaskVo) {
                TaskVo vo = (TaskVo) args.get(0);
                Task task = taskService.createTaskQuery().taskId(vo.getTaskId()).singleResult();
                String processInstanceId = null;
                if (ObjectUtil.isNull(task)) {
                    HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(vo.getTaskId()).singleResult();
                    if (ObjectUtil.isNotNull(historicTaskInstance)) {
                        processInstanceId = historicTaskInstance.getProcessInstanceId();
                    }
                } else {
                    processInstanceId = task.getProcessInstanceId();
                }
                if (StringUtils.isNotBlank(processInstanceId)) {
                    List<Comment> datas = taskService.getProcessInstanceComments(processInstanceId);
                    if (CollectionUtil.isNotEmpty(datas)) {
                        Comment data = datas.get(0);
                        userId = Long.valueOf(data.getUserId());
                        msg = data.getFullMessage();
                    }
                    record = flowableRecordService.getById(processInstanceId);
                }
                if (vo.getCcToVos() !=null && vo.getCcToVos().length > 0){
                    List<Long> ccList =  Arrays.stream(vo.getCcToVos()).map(e -> Long.parseLong(e.getUserId())).collect(Collectors.toList());
                    Map<String, Object> variables = new HashMap<>();
                    variables.put("cc", StringUtils.join(Arrays.stream(vo.getCcToVos()).map(e -> Long.parseLong(e.getUserId())).collect(Collectors.toList()),","));
                    runtimeService.setVariables(processInstanceId, variables);
                }
            } else {
                // ID
                Long id = (Long) args.get(0);
                userId = (Long) args.get(1);
                nickName = (String) args.get(2);
                FlowableRecordQuery recordQuery = new FlowableRecordQuery();
                recordQuery.setSourceId(id);
                record = flowableRecordService.getOne(WhereEntityTool.invoke(recordQuery));
                msg = String.format("[%s]退回", nickName);
            }

            if (ObjectUtil.isNotNull(record) && FlowableConstant.FLOWABLE_OTHER.contains(record.getRecordType()) && ObjectUtil.isNotNull(record.getSourceId()) && !ApprovalDescriptionEnum.C.getValue().equals(record.getStatus())) {
                flowableRecordService.removeById(record.getProcessInstanceId());

                TaskQuery query = taskService.createTaskQuery();
                query.processInstanceId(record.getProcessInstanceId());
                query.taskCategory(FlowableConstant.CATEGORY_TODO);
                Task task= null;
                long count = query.count();
                if (count >1){
                    task = query.list().get(0);
                }else {
                    task = query.singleResult();
                }

                // 终止流程
                TaskVo taskVo = new TaskVo();
                taskVo.setTaskId(task.getId());
                taskVo.setMessage(msg);
                taskVo.setProcessInstanceId(record.getProcessInstanceId());
                flowableTaskService.stopProcessInstance(taskVo, userId);
            }
        }
    }
}
